<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>前端构建工具 | TBlog</title>
    <meta name="description" content="TBlog with vitePress">
    <link rel="stylesheet" href="/interview/assets/style.9156a4ed.css">
    <link rel="modulepreload" href="/interview/assets/Home.b86443e2.js">
    <link rel="modulepreload" href="/interview/assets/app.49accf37.js">
    <link rel="modulepreload" href="/interview/assets/WebPack_index.md.49f185a6.lean.js">
    <link rel="modulepreload" href="/interview/assets/app.49accf37.js">
    <link rel="icon" href="/favicon.ico">
    <meta name="twitter:title" content="前端构建工具 | TBlog">
    <meta property="og:title" content="前端构建工具 | TBlog">
  </head>
  <body>
    <div id="app"><!--[--><div class="theme"><header class="nav-bar" data-v-7161a24b><div class="sidebar-button" data-v-7161a24b><svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class></path></svg></div><a class="nav-bar-title" href="/interview/" aria-label="TBlog, back to home" data-v-7161a24b data-v-4a583abe><!----> TBlog</a><div class="flex-grow" data-v-7161a24b></div><div class="nav" data-v-7161a24b><nav class="nav-links" data-v-7161a24b data-v-15acbf05><!--[--><div class="item" data-v-15acbf05><div class="nav-link" data-v-15acbf05 data-v-641633f9><a class="item isExternal" href="http://101.43.7.188:66" target="_blank" rel="noopener noreferrer" data-v-641633f9>Music <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-641633f9><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><div class="item" data-v-15acbf05><div class="nav-link" data-v-15acbf05 data-v-641633f9><a class="item isExternal" href="http://101.43.7.188:80" target="_blank" rel="noopener noreferrer" data-v-641633f9>CMC <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-641633f9><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><div class="item" data-v-15acbf05><div class="nav-link" data-v-15acbf05 data-v-641633f9><a class="item isExternal" href="https://juejin.cn/user/2163479676978734/posts" target="_blank" rel="noopener noreferrer" data-v-641633f9>掘金 <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-641633f9><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><div class="item" data-v-15acbf05><div class="nav-link" data-v-15acbf05 data-v-641633f9><a class="item isExternal" href="https://gitee.com/tu_zhiwei98" target="_blank" rel="noopener noreferrer" data-v-641633f9>Gitee <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-641633f9><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><!----><!----></nav></div><!--[--><!--]--></header><aside class="sidebar" data-v-6b49cdcd><nav class="nav-links nav" data-v-6b49cdcd data-v-15acbf05><!--[--><div class="item" data-v-15acbf05><div class="nav-link" data-v-15acbf05 data-v-641633f9><a class="item isExternal" href="http://101.43.7.188:66" target="_blank" rel="noopener noreferrer" data-v-641633f9>Music <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-641633f9><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><div class="item" data-v-15acbf05><div class="nav-link" data-v-15acbf05 data-v-641633f9><a class="item isExternal" href="http://101.43.7.188:80" target="_blank" rel="noopener noreferrer" data-v-641633f9>CMC <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-641633f9><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><div class="item" data-v-15acbf05><div class="nav-link" data-v-15acbf05 data-v-641633f9><a class="item isExternal" href="https://juejin.cn/user/2163479676978734/posts" target="_blank" rel="noopener noreferrer" data-v-641633f9>掘金 <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-641633f9><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><div class="item" data-v-15acbf05><div class="nav-link" data-v-15acbf05 data-v-641633f9><a class="item isExternal" href="https://gitee.com/tu_zhiwei98" target="_blank" rel="noopener noreferrer" data-v-641633f9>Gitee <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-641633f9><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><!----><!----></nav><!--[--><!--]--><ul class="sidebar-links" data-v-6b49cdcd><!--[--><li class="sidebar-link"><p class="sidebar-link-item">Vue3.2X</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Vue/">基本语法&amp;使用</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Vue/VueX">VueX4.x</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Vue/Router">Router4.x</a><!----></li><li class="sidebar-link"><p class="sidebar-link-item">部分源码解析</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Vue/reactive">响应式系统</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Vue/source/Watch">Watch</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Vue/source/nextTick">nextTick</a><!----></li></ul></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">WebPack</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item active" href="/interview/WebPack/">基础配置</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#webpack-工作流程">webpack 工作流程</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#context">context</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#entry-类型">Entry 类型</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#chunk-名称">Chunk 名称</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#配置动态-entry">配置动态 Entry</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#多入口文件">多入口文件</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#filename">filename</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#chunkfilename">chunkFilename</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#path">path</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#publicpath">publicPath</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#loader">Loader</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#配置-loader">配置 Loader</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#忽略第三方库-noparse">忽略第三方库 noParse</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#配置解析-模块化语法-parser">配置解析 模块化语法 parser</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#切换-es5-6-mainfields">切换 ES5/6 mainFields</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#路径别名-alias">路径别名 alias</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#省略后缀-extensions">省略后缀 extensions</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#缩写路径-modules">缩写路径 modules</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#externals">externals</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#enforceextension">enforceExtension</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#host">host</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#port">port</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#模块热替换-hmr">模块热替换 HMR</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#hot-livereload">hot/ liveReload</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="#proxy">Proxy</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#historyapifallback">HistoryApiFallback</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#contentbase">contentBase</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#注入响应头-headers">注入响应头 headers</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#开启白名单-allowedhosts">开启白名单 allowedHosts</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#host-检查-disablehostcheck">HOST 检查 disableHostCheck</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#https">https</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#开启压缩-compress">开启压缩 compress</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#使用">使用</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#app1-声明共用模块">App1 声明共用模块</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#app2-引入共用模块">App2 引入共用模块</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#在-app2-中使用-app1-的模块">在 App2 中使用 App1 的模块</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/WebPack/optimize">优化方案</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/WebPack/common">常见的Loader以及Plugin</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/WebPack/custom">自定义Loader以及Plugin</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/WebPack/advanced">手写简单的MY_Webpack</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">Javascript</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Javascript/">基本语法</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Javascript/advanced">高级语法</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">TypeScript</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/TypeScript/">基本语法</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/TypeScript/combat">业务实战</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/TypeScript/advanced">高阶使用</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">浏览器相关</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Browser/">基本原理</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Browser/plugin">浏览器插件</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Browser/advanced">深入原理</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">计算机网络</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Network/">计算机网络</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Network/security">前端安全</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">HTML/CSS</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/CSS/">CSS</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/HTML/">HTML</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">Vite2.X</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Vite/">基础配置</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Vite/optimize">原理以及优化</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">Node</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Node/">基本知识</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Node/pit">踩坑记录</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">其他前端工具</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Git/">Git</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Jenkins/">Jenkins</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/npm/">包管理工具</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">踩坑记录以及经验</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Pit/">踩坑</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/solution/">一些解决方案</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">面经</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Interview/">xxx面试</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Interview/two">xxX面试</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">个人学习历程</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Myself/">个人情况说明</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Myself/pre">入行工作前</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="/interview/Myself/one">工作第一年</a><!----></li></ul></li><!--]--></ul><!--[--><!--]--></aside><!-- TODO: make this button accessible --><div class="sidebar-mask"></div><main class="page" data-v-7eddb2c4><div class="container" data-v-7eddb2c4><!--[--><!--]--><div style="position:relative;" class="content" data-v-7eddb2c4><div><h1 id="前端构建工具"><a class="header-anchor" href="#前端构建工具" aria-hidden="true">#</a> 前端构建工具</h1><p>但是这些东西都有一个共同点：源代码无法直接运行，必须通过转换后才可以正常运行。</p><p>构建就是做这件事情，把源代码转换成发布到线上的可执行 JavaScrip、CSS、HTML 代码，包括如下内容。</p><ul><li>代码转换：TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等。</li><li>文件优化：压缩 JavaScript、CSS、HTML 代码，压缩合并图片等。</li><li>代码分割：提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。</li><li>模块合并：在采用模块化的项目里会有很多个模块和文件，需要构建功能把模块分类合并成一个文件。</li><li>自动刷新：监听本地源代码的变化，自动重新构建、刷新浏览器。</li><li>代码校验：在代码被提交到仓库前需要校验代码是否符合规范，以及单元测试是否通过。</li><li>自动发布：更新完代码后，自动构建出线上发布代码并传输给发布系统。</li></ul><p>构建其实是工程化、自动化思想在前端开发中的体现，把一系列流程用代码去实现，让代码自动化地执行这一系列复杂的流程。 构建给前端开发注入了更大的活力，解放了我们的生产力。</p><h2 id="webpack-工作流程"><a class="header-anchor" href="#webpack-工作流程" aria-hidden="true">#</a> webpack 工作流程</h2><ol><li>Webpack 启动后会从 Entry 里配置的 Module 开始递归解析 Entry 依赖的所有 Module。</li><li>每找到一个 Module， 就会根据配置的 Loader 去找出对应的转换规则</li><li>对 Module 进行转换后，再解析出当前 Module 依赖的 Module</li><li>这些模块会以 Entry 为单位进行分组，一个 Entry 和其所有依赖的 Module 被分到一个组也就是一个 Chunk。</li><li>最后 Webpack 会把所有 Chunk 转换成文件输出。</li><li>在整个流程中 Webpack 会在恰当的时机执行 Plugin 里定义的逻辑</li></ol><h1 id="webpack-安装以及介绍"><a class="header-anchor" href="#webpack-安装以及介绍" aria-hidden="true">#</a> Webpack 安装以及介绍</h1><p>是一个打包模块化 JavaScript 的工具，它会从 <code>main.js</code> 出发，识别出源码中的模块化导入语句， 递归的寻找出入口文件的所有依赖，把入口和其所有依赖打包到一个单独的文件中。</p><div class="language-apl"><pre><code><span class="token comment"># npm i -D 是 npm install --save-dev 的简写，是指安装模块并保存到 package.json 的 devDependencies</span>
<span class="token comment"># 安装最新稳定版</span>
npm i <span class="token function">-</span>D webpack webpack<span class="token function">-</span>cli

<span class="token comment"># 安装指定版本</span>
npm i <span class="token function">-</span>D webpack<span class="token dyadic-operator operator">@</span><span class="token function">&lt;</span>version<span class="token function">&gt;</span>

<span class="token comment"># 安装最新体验版本</span>
npm i <span class="token function">-</span>D webpack<span class="token dyadic-operator operator">@</span>beta
</code></pre></div><p>运行途径</p><ul><li>执行 webpack 命令,会执行 <code>node_modules/.bin/webpack</code>。</li><li>webpack 在执行时依赖与 webpack-cli 的, 需要同时安装</li><li>在 <a href="https://webpack.wuhaolin.cn/1%E5%85%A5%E9%97%A8/%E5%B8%B8%E8%A7%81%E7%9A%84%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7%E5%8F%8A%E5%AF%B9%E6%AF%94/npm_script.md" target="_blank" rel="noopener noreferrer">Npm Script</a> 里定义的任务会优先使用本项目下的 Webpack，代码如下：</li></ul><div class="language-apl"><pre><code>&quot;scripts&quot;<span class="token dfn builtin">:</span> <span class="token dfn builtin">{</span>
    &quot;start&quot;<span class="token dfn builtin">:</span> &quot;webpack <span class="token function">-</span><span class="token function">-</span>config webpack<span class="token dyadic-operator operator">.</span>config<span class="token dyadic-operator operator">.</span>js&quot;
<span class="token dfn builtin">}</span>
</code></pre></div><p>核心概念</p><div class="language-cobol"><pre><code><span class="token keyword">Entry</span>：  入口，Webpack 执行构建的第一步将从 <span class="token keyword">Entry</span> 开始，可抽象成输入。
Module：	模块，在 Webpack 里一切皆模块，一个模块对应着一个文件。Webpack 会从配置的 <span class="token keyword">Entry</span> 开始递归找出所有依赖的模块。
Chunk：	代码块，一个 Chunk 由多个模块组合而成，用于代码合并与分割。
Loader：	模块转换器，用于把模块原内容按照需求转换成新内容。
Plugin：	扩展插件，在 Webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要的事情。
<span class="token keyword">Output</span>：	输出结果，在 Webpack 经过一系列处理并得出最终想要的代码后输出结果。
</code></pre></div><p>Webpack 启动后会从 Entry 里配置的 Module 开始递归解析 Entry 依赖的所有 Module。 每找到一个 Module， 就会根据配置的 Loader 去找出对应的转换规则，对 Module 进行转换后，再解析出当前 Module 依赖的 Module。 这些模块会以 Entry 为单位进行分组，一个 Entry 和其所有依赖的 Module 被分到一个组也就是一个 Chunk。最后 Webpack 会把所有 Chunk 转换成文件输出。 在整个流程中 Webpack 会在恰当的时机执行 Plugin 里定义的逻辑</p><ul><li>webpack = web Package</li><li>webpack 是一个现代 JS 应用程序的静态模块打包器 (module bundler) <ul><li>模块 (指的是模块化开发)</li><li>打包 (将各个模块, 按照一定的规则组装起来)</li></ul></li></ul><img src="/interview/assets/打包过程.f9222e90.png" style="zoom:100%;"><h1 id="entry-入口"><a class="header-anchor" href="#entry-入口" aria-hidden="true">#</a> Entry(入口)</h1><p>告诉 webpack 应该使用哪个模块 作为构建依赖的开始, 必填项</p><ul><li>在我们打包时,第一个被访问的源码文件</li><li>默认是 src/index.js (可以通过配置文件指定)</li><li>Webpack 执行构建的第一步将从入口开始搜寻及递归解析出所有入口依赖的模块.</li></ul><img src="/interview/assets/入口文件.58dbc68a.png" style="zoom:100%;"><div class="language-js"><pre><code><span class="token comment">///     基础的单入口 ///</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  entry<span class="token operator">:</span> <span class="token string">&quot;./src/index.js&quot;</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="context"><a class="header-anchor" href="#context" aria-hidden="true">#</a> context</h2><p>Webpack 在寻找相对路径的文件时会以 <code>context</code> 为根目录，<code>context</code> 默认为执行启动 Webpack 时所在的当前工作目录置</p><div class="language-js"><pre><code>module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  context<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;app&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><p>注意， <code>context</code> 必须是一个绝对路径的字符串。 除此之外，还可以通过在启动 Webpack 时带上参数 <code>webpack --context</code> 来设置 <code>context</code>。</p><p>因为 Entry 的路径和其依赖的模块的路径可能采用相对于 <code>context</code> 的路径来描述，<code>context</code> 会影响到这些相对路径所指向的真实文件。</p><h2 id="entry-类型"><a class="header-anchor" href="#entry-类型" aria-hidden="true">#</a> Entry 类型</h2><p>Entry 类型可以是以下三种中的一种或者相互组合：</p><table><thead><tr><th>类型</th><th>例子</th><th>含义</th></tr></thead><tbody><tr><td>string</td><td><code>&#39;./app/entry&#39;</code></td><td>入口模块的文件路径，可以是相对路径。</td></tr><tr><td>array</td><td><code>[&#39;./app/entry1&#39;, &#39;./app/entry2&#39;]</code></td><td>入口模块的文件路径，可以是相对路径。</td></tr><tr><td>object</td><td><code>{ a: &#39;./app/entry-a&#39;, b: [&#39;./app/entry-b1&#39;, &#39;./app/entry-b2&#39;]}</code></td><td>配置多个入口，每个入口生成一个 Chunk</td></tr></tbody></table><p>如果是 <code>array</code> 类型，则搭配 <code>output.library</code> 配置项使用时，只有数组里的最后一个入口文件的模块会被导出。</p><h2 id="chunk-名称"><a class="header-anchor" href="#chunk-名称" aria-hidden="true">#</a> Chunk 名称</h2><p>Webpack 会为每个生成的 Chunk 取一个名称，Chunk 的名称和 Entry 的配置有关：</p><ul><li>如果 <code>entry</code> 是一个 <code>string</code> 或 <code>array</code>，就只会生成一个 Chunk，这时 Chunk 的名称是 <code>main</code>；</li><li>如果 <code>entry</code> 是一个 <code>object</code>，就可能会出现多个 Chunk，这时 Chunk 的名称是 <code>object</code> 键值对里键的名称。</li></ul><h2 id="配置动态-entry"><a class="header-anchor" href="#配置动态-entry" aria-hidden="true">#</a> 配置动态 Entry</h2><p>假如项目里有多个页面需要为每个页面的入口配置一个 Entry ，但这些页面的数量可能会不断增长，则这时 Entry 的配置会受到到其他因素的影响导致不能写成静态的值。其解决方法是把 Entry 设置成一个函数去动态返回上面所说的配置，代码如下：</p><div class="language-js"><pre><code><span class="token comment">// 同步函数</span>
<span class="token function-variable function">entry</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    a<span class="token operator">:</span> <span class="token string">&quot;./pages/a&quot;</span><span class="token punctuation">,</span>
    b<span class="token operator">:</span> <span class="token string">&quot;./pages/b&quot;</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment">// 异步函数</span>
<span class="token function-variable function">entry</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      a<span class="token operator">:</span> <span class="token string">&quot;./pages/a&quot;</span><span class="token punctuation">,</span>
      b<span class="token operator">:</span> <span class="token string">&quot;./pages/b&quot;</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="多入口文件"><a class="header-anchor" href="#多入口文件" aria-hidden="true">#</a> 多入口文件</h2><p><strong>通过 html-webpack-plugin 插件生成多个实例</strong></p><div class="language-javascript"><pre><code><span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">&quot;path&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> HtmlWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">&quot;html-webpack-plugin&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  mode<span class="token operator">:</span> <span class="token string">&quot;development&quot;</span><span class="token punctuation">,</span> <span class="token comment">// 开发模式</span>
  entry<span class="token operator">:</span> <span class="token punctuation">{</span>
    main<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;../src/main.js&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    header<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;../src/header.js&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  output<span class="token operator">:</span> <span class="token punctuation">{</span>
    filename<span class="token operator">:</span> <span class="token string">&quot;[name].[hash:8].js&quot;</span><span class="token punctuation">,</span> <span class="token comment">// 打包后的文件名称</span>
    path<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;../dist&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// 打包后的目录</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  plugins<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      template<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;../public/index.html&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      filename<span class="token operator">:</span> <span class="token string">&quot;index.html&quot;</span><span class="token punctuation">,</span>
      chunks<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;main&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// 与入口文件对应的模块名</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      template<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;../public/header.html&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      filename<span class="token operator">:</span> <span class="token string">&quot;header.html&quot;</span><span class="token punctuation">,</span>
      chunks<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;header&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// 与入口文件对应的模块名</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><h1 id="output"><a class="header-anchor" href="#output" aria-hidden="true">#</a> Output</h1><ul><li>打包后, 输出的文件名称</li><li>默认是 dist/main.js</li></ul><p><code>output</code> 配置如何输出最终想要的代码。<code>output</code> 是一个 <code>object</code>，里面包含一系列配置项，下面分别介绍它们。</p><h2 id="filename"><a class="header-anchor" href="#filename" aria-hidden="true">#</a> filename</h2><p><code>output.filename</code> 配置输出文件的名称，为 string 类型。 如果只有一个输出文件，则可以把它写成静态不变的：</p><div class="language-js"><pre><code>filename<span class="token operator">:</span> <span class="token string">&quot;bundle.js&quot;</span><span class="token punctuation">;</span>
</code></pre></div><p>但是在有多个 Chunk 要输出时，就需要借助模版和变量了。前面说到 Webpack 会为每个 Chunk 取一个名称，可以根据 Chunk 的名称来区分输出的文件名：</p><div class="language-js"><pre><code>filename<span class="token operator">:</span> <span class="token string">&quot;[name].js&quot;</span><span class="token punctuation">;</span>
</code></pre></div><p>代码里的 <code>[name]</code> 代表用内置的 <code>name</code> 变量去替换<code>[name]</code>，这时你可以把它看作一个字符串模块函数， 每个要输出的 Chunk 都会通过这个函数去拼接出输出的文件名称。</p><p>内置变量除了 <code>name</code> 还包括：</p><table><thead><tr><th>变量名</th><th>含义</th></tr></thead><tbody><tr><td>id</td><td>Chunk 的唯一标识，从 0 开始</td></tr><tr><td>name</td><td>Chunk 的名称</td></tr><tr><td>hash</td><td>Chunk 的唯一标识的 Hash 值</td></tr><tr><td>chunkhash</td><td>Chunk 内容的 Hash 值</td></tr></tbody></table><p>其中 <code>hash</code> 和 <code>chunkhash</code> 的长度是可指定的，<code>[hash:8]</code> 代表取 8 位 Hash 值，默认是 20 位。</p><blockquote><p>注意 <a href="https://github.com/webpack-contrib/extract-text-webpack-plugin" target="_blank" rel="noopener noreferrer">ExtractTextWebpackPlugin</a> 插件是使用 <code>contenthash</code> 来代表哈希值而不是 <code>chunkhash</code>， 原因在于 ExtractTextWebpackPlugin 提取出来的内容是代码内容本身而不是由一组模块组成的 Chunk。</p></blockquote><h2 id="chunkfilename"><a class="header-anchor" href="#chunkfilename" aria-hidden="true">#</a> chunkFilename</h2><p><code>output.chunkFilename</code> 配置无入口的 Chunk 在输出时的文件名称。 chunkFilename 和上面的 filename 非常类似，但 chunkFilename 只用于指定在运行过程中生成的 Chunk 在输出时的文件名称。 常见的会在运行时生成 Chunk 场景有在使用 CommonChunkPlugin、使用 <code>import(&#39;path/to/module&#39;)</code> 动态加载等时。 chunkFilename 支持和 filename 一致的内置变量。</p><h2 id="path"><a class="header-anchor" href="#path" aria-hidden="true">#</a> path</h2><p><code>output.path</code> 配置输出文件存放在本地的目录，必须是 string 类型的绝对路径。通常通过 Node.js 的 <code>path</code> 模块去获取绝对路径：</p><div class="language-js"><pre><code>path<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;dist_[hash]&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="publicpath"><a class="header-anchor" href="#publicpath" aria-hidden="true">#</a> publicPath</h2><p>在复杂的项目里可能会有一些构建出的资源需要异步加载，加载这些异步资源需要对应的 URL 地址。</p><p><code>output.publicPath</code> 配置发布到线上资源的 URL 前缀，为 string 类型。 默认值是空字符串 <code>&#39;&#39;</code>，即使用相对路径。</p><p>这样说可能有点抽象，举个例子，需要把构建出的资源文件上传到 CDN 服务上，以利于加快页面的打开速度。配置代码如下：</p><div class="language-js"><pre><code>filename<span class="token operator">:</span> <span class="token string">&quot;[name]_[chunkhash:8].js&quot;</span><span class="token punctuation">;</span>
publicPath<span class="token operator">:</span> <span class="token string">&quot;https://cdn.example.com/assets/&quot;</span><span class="token punctuation">;</span>
</code></pre></div><p>这时发布到线上的 HTML 在引入 JavaScript 文件时就需要：</p><div class="language-html"><pre><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://cdn.example.com/assets/a_12345678.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>使用该配置项时要小心，稍有不慎将导致资源加载 404 错误。</p><p><code>output.path</code> 和 <code>output.publicPath</code> 都支持字符串模版，内置变量只有一个：<code>hash</code> 代表一次编译操作的 Hash 值。</p><h1 id="mode"><a class="header-anchor" href="#mode" aria-hidden="true">#</a> Mode</h1><ul><li><p>用来区分环境的关键字</p><ul><li>不同环境的打包逻辑不同</li></ul></li><li><p>三种模式</p><ol><li>development (自动优化打包速度, 添加一些调试过程中的辅助)</li><li>production (自动优化打包结果,默认压缩)</li><li>none (允许最原始的打包,不做任何处理)</li></ol></li></ul><h1 id="module"><a class="header-anchor" href="#module" aria-hidden="true">#</a> Module</h1><h2 id="loader"><a class="header-anchor" href="#loader" aria-hidden="true">#</a> Loader</h2><ul><li>专门用来处理一类文件(非 JS)的工具</li><li>webpack 默认只能识别 JS,想要处理其他类型的文件,需要对应的 loader</li></ul><p><code>module</code> 配置如何处理模块。</p><h2 id="配置-loader"><a class="header-anchor" href="#配置-loader" aria-hidden="true">#</a> 配置 Loader</h2><p><code>rules</code> 配置模块的读取和解析规则，通常用来配置 Loader。其类型是一个数组，数组里每一项都描述了如何去处理部分文件。 配置一项 <code>rules</code> 时大致通过以下方式：</p><ol><li>条件匹配：通过 <code>test</code> 、 <code>include</code> 、 <code>exclude</code> 三个配置项来命中 Loader 要应用规则的文件。</li><li>应用规则：对选中后的文件通过 <code>use</code> 配置项来应用 Loader，可以只应用一个 Loader 或者按照从后往前的顺序应用一组 Loader，同时还可以分别给 Loader 传入参数。</li><li>重置顺序：一组 Loader 的执行顺序默认是从右到左执行，通过 <code>enforce</code> 选项可以让其中一个 Loader 的执行顺序放到最前或者最后。</li></ol><p>通过一个例子来说明具体使用方法：</p><div class="language-js"><pre><code>module<span class="token operator">:</span> <span class="token punctuation">{</span>
  rules<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      <span class="token comment">// 命中 JavaScript 文件</span>
      test<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token comment">// 用 babel-loader 转换 JavaScript 文件</span>
      <span class="token comment">// ?cacheDirectory 表示传给 babel-loader 的参数，用于缓存 babel 编译结果加快重新编译速度</span>
      use<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;babel-loader?cacheDirectory&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token comment">// 只命中src目录里的js文件，加快 Webpack 搜索速度</span>
      include<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;src&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token comment">// 命中 SCSS 文件</span>
      test<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.scss$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token comment">// 使用一组 Loader 去处理 SCSS 文件。</span>
      <span class="token comment">// 处理顺序为从后到前，即先交给 sass-loader 处理，再把结果交给 css-loader 最后再给 style-loader。</span>
      use<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;style-loader&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;css-loader&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;sass-loader&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token comment">// 排除 node_modules 目录下的文件</span>
      exclude<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;node_modules&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
      <span class="token comment">// 对非文本文件采用 file-loader 加载</span>
      test<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      use<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;file-loader&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>在 Loader 需要传入很多参数时，你还可以通过一个 Object 来描述，例如在上面的 babel-loader 配置中有如下代码：</p><div class="language-js"><pre><code>use<span class="token operator">:</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    loader<span class="token operator">:</span> <span class="token string">&quot;babel-loader&quot;</span><span class="token punctuation">,</span>
    options<span class="token operator">:</span> <span class="token punctuation">{</span>
      cacheDirectory<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token comment">// enforce:&#39;post&#39; 的含义是把该 Loader 的执行顺序放到最后</span>
    <span class="token comment">// enforce 的值还可以是 pre，代表把 Loader 的执行顺序放到最前面</span>
    enforce<span class="token operator">:</span> <span class="token string">&quot;post&quot;</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token comment">// 省略其它 Loader</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
</code></pre></div><p>上面的例子中 <code>test include exclude</code> 这三个命中文件的配置项只传入了一个字符串或正则，其实它们还都支持数组类型，使用如下：</p><div class="language-js"><pre><code><span class="token punctuation">{</span>
  test<span class="token operator">:</span><span class="token punctuation">[</span>
    <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.jsx?$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
    <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.tsx?$</span><span class="token regex-delimiter">/</span></span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  include<span class="token operator">:</span><span class="token punctuation">[</span>
    path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&#39;src&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&#39;tests&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  exclude<span class="token operator">:</span><span class="token punctuation">[</span>
    path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&#39;node_modules&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&#39;bower_modules&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span>
<span class="token punctuation">}</span>
</code></pre></div><p>数组里的每项之间是<strong>或</strong>的关系，即文件路径符合数组中的任何一个条件就会被命中。</p><h2 id="忽略第三方库-noparse"><a class="header-anchor" href="#忽略第三方库-noparse" aria-hidden="true">#</a> 忽略第三方库 noParse</h2><p><code>noParse</code> 配置项可以让 Webpack 忽略对部分没采用模块化的文件的递归解析和处理，这样做的好处是能提高构建性能。 原因是一些库例如 jQuery 、ChartJS 它们庞大又没有采用模块化标准，让 Webpack 去解析这些文件耗时又没有意义。</p><p><code>noParse</code> 是可选配置项，类型需要是 <code>RegExp</code>、<code>[RegExp]</code>、<code>function</code> 其中一个。</p><p>例如想要忽略掉 jQuery 、ChartJS，可以使用如下代码：</p><div class="language-js"><pre><code><span class="token comment">// 使用正则表达式</span>
noParse<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">jquery|chartjs</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">;</span>

<span class="token comment">// 使用函数，从 Webpack 3.0.0 开始支持</span>
<span class="token function-variable function">noParse</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">content</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// content 代表一个模块的文件路径</span>
  <span class="token comment">// 返回 true or false</span>
  <span class="token keyword">return</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">jquery|chartjs</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>content<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><blockquote><p>注意被忽略掉的文件里不应该包含 <code>import</code> 、 <code>require</code> 、 <code>define</code> 等模块化语句，不然会导致构建出的代码中包含无法在浏览器环境下执行的模块化语句。</p></blockquote><h2 id="配置解析-模块化语法-parser"><a class="header-anchor" href="#配置解析-模块化语法-parser" aria-hidden="true">#</a> 配置解析 模块化语法 parser</h2><p>因为 Webpack 是以模块化的 JavaScript 文件为入口，所以内置了对模块化 JavaScript 的解析功能，支持 AMD、CommonJS、SystemJS、ES6。 <code>parser</code> 属性可以更细粒度的配置哪些模块语法要解析哪些不解析，和 <code>noParse</code> 配置项的区别在于 <code>parser</code> 可以精确到语法层面， 而 <code>noParse</code> 只能控制哪些文件不被解析。 <code>parser</code> 使用如下：</p><div class="language-js"><pre><code>module<span class="token operator">:</span> <span class="token punctuation">{</span>
  rules<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      test<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      use<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;babel-loader&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      parser<span class="token operator">:</span> <span class="token punctuation">{</span>
        amd<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 禁用 AMD</span>
        commonjs<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 禁用 CommonJS</span>
        system<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 禁用 SystemJS</span>
        harmony<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 禁用 ES6 import/export</span>
        requireInclude<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 禁用 require.include</span>
        requireEnsure<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 禁用 require.ensure</span>
        requireContext<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 禁用 require.context</span>
        browserify<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 禁用 browserify</span>
        requireJs<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// 禁用 requirejs</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p><code>react$</code> 只会命中以 <code>react</code> 结尾的导入语句，即只会把 <code>import &#39;react&#39;</code> 关键字替换成 <code>import &#39;/path/to/react.min.js&#39;</code>。</p><h2 id="切换-es5-6-mainfields"><a class="header-anchor" href="#切换-es5-6-mainfields" aria-hidden="true">#</a> 切换 ES5/6 mainFields</h2><p>有一些第三方模块会针对不同环境提供几分代码。 例如分别提供采用 ES5 和 ES6 的 2 份代码，这 2 份代码的位置写在 <code>package.json</code> 文件里，如下：</p><div class="language-json"><pre><code><span class="token punctuation">{</span>
  <span class="token property">&quot;jsnext:main&quot;</span><span class="token operator">:</span> <span class="token string">&quot;es/index.js&quot;</span><span class="token punctuation">,</span> <span class="token comment">// 采用 ES6 语法的代码入口文件</span>
  <span class="token property">&quot;main&quot;</span><span class="token operator">:</span> <span class="token string">&quot;lib/index.js&quot;</span> <span class="token comment">// 采用 ES5 语法的代码入口文件</span>
<span class="token punctuation">}</span>
</code></pre></div><p>Webpack 会根据 <code>mainFields</code> 的配置去决定优先采用那份代码，<code>mainFields</code> 默认如下：</p><div class="language-js"><pre><code>mainFields<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;browser&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;main&quot;</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</code></pre></div><p>Webpack 会按照数组里的顺序去<code>package.json</code> 文件里寻找，只会使用找到的第一个。</p><p>假如你想优先采用 ES6 的那份代码，可以这样配置：</p><div class="language-js"><pre><code>mainFields<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;jsnext:main&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;browser&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;main&quot;</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</code></pre></div><h1 id="资源模块（asset-modules）"><a class="header-anchor" href="#资源模块（asset-modules）" aria-hidden="true">#</a> 资源模块（Asset Modules）</h1><p>资源模块(asset module)是一种模块类型，它允许使用资源文件（字体，图标等）而无需配置额外 loader。</p><p>在 webpack 5 之前，通常使用：</p><ul><li><p>raw-loader 将文件导入为字符串</p></li><li><p>url-loader 将文件作为 data URI 内联到 bundle 中</p></li><li><p>file-loader 将文件发送到输出目录</p></li></ul><p>资源模块类型(asset module type)，通过添加 4 种新的模块类型，来替换所有这些 loader：</p><ul><li><p>asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。</p></li><li><p>asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。</p></li><li><p>asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。</p></li><li><p>asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader，并且配置资源体积限制实现。</p></li></ul><p>即：不需要上述 loader，我们在 Webpack 5 中，也可以处理图片字体等资源文件</p><p>例如：</p><div class="language-javascript"><pre><code>module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token comment">// ......</span>

  <span class="token comment">// 模块配置</span>
  module<span class="token operator">:</span> <span class="token punctuation">{</span>
    rules<span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token comment">// 处理图片</span>
      <span class="token comment">// {</span>
      <span class="token comment">//   test: /\.(png|gif|jpe?g)$/i,</span>
      <span class="token comment">//   use: {</span>
      <span class="token comment">//     loader: &quot;url-loader&quot;,</span>
      <span class="token comment">//     options: {</span>
      <span class="token comment">//       // 指定图片大小，小于该数值的图片，会被转成 base64</span>
      <span class="token comment">//       limit: 8 * 1024, // 8 kb</span>
      <span class="token comment">//       // [name] 是图片原来的名称</span>
      <span class="token comment">//       // [ext] 是图片原来的后缀名</span>
      <span class="token comment">//       name: &quot;image/[name].[ext]&quot;,</span>
      <span class="token comment">//       // url-loader 默认采用 ES Modules 规范进行解析，但是 html-loader 引入图片使用的是 CommonJS 规范</span>
      <span class="token comment">//       // 解决：关闭 url-loader 默认的 ES Modules 规范，强制 url-loader 使用 CommonJS 规范进行打包</span>
      <span class="token comment">//       esModule: false</span>
      <span class="token comment">//     }</span>
      <span class="token comment">//   }</span>
      <span class="token comment">// },</span>
</code></pre></div><div class="language-javascript"><pre><code>  <span class="token comment">// 通过资源模块来处理图片</span>
  <span class="token punctuation">{</span>
    test<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(png|gif|jpe?g)$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">i</span></span><span class="token punctuation">,</span>
    type<span class="token operator">:</span> <span class="token string">&#39;asset&#39;</span><span class="token punctuation">,</span>
    <span class="token comment">// 现在，webpack 将按照默认条件，自动地在 resource 和 inline 之间进行选择：</span>
    <span class="token comment">// 小于 8kb 的文件，将会视为 inline 模块类型，否则会被视为 resource 模块类型。</span>
    <span class="token comment">// 自定义设置</span>
    parser<span class="token operator">:</span> <span class="token punctuation">{</span>
      dataUrlCondition<span class="token operator">:</span> <span class="token punctuation">{</span>
        maxSize<span class="token operator">:</span> <span class="token number">8</span> <span class="token operator">*</span> <span class="token number">1024</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    generator<span class="token operator">:</span> <span class="token punctuation">{</span>
      filename<span class="token operator">:</span> <span class="token string">&quot;image/[name][ext]&quot;</span> <span class="token comment">// 单独指定 名字</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token comment">// 通过资源模块来处理字体</span>
  <span class="token punctuation">{</span>
    test<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(eot|svg|ttf|woff|woff2)$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">i</span></span><span class="token punctuation">,</span>
    <span class="token comment">// use: {</span>
    <span class="token comment">//   loader: &#39;file-loader&#39;,</span>
    <span class="token comment">//   options: {</span>
    <span class="token comment">//     name: &#39;fonts/[name].[ext]&#39;</span>
    <span class="token comment">//   }</span>
    <span class="token comment">// }</span>
    type<span class="token operator">:</span> <span class="token string">&#39;asset&#39;</span><span class="token punctuation">,</span>
    parser<span class="token operator">:</span> <span class="token punctuation">{</span>
      dataUrlCondition<span class="token operator">:</span> <span class="token punctuation">{</span>
        maxSize<span class="token operator">:</span> <span class="token number">8</span> <span class="token operator">*</span> <span class="token number">1024</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    generator<span class="token operator">:</span> <span class="token punctuation">{</span>
      filename<span class="token operator">:</span> <span class="token string">&quot;fonts/[name][ext]&quot;</span> <span class="token comment">// 单独指定 名字</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token comment">// ......</span>
<span class="token punctuation">]</span>
</code></pre></div><h1 id="resolve"><a class="header-anchor" href="#resolve" aria-hidden="true">#</a> Resolve</h1><p>resolve 用于设置模块如何被解析: 可以帮助 webpack 从每个 require/import 语句中,找到需要引入到合适的模块代码</p><p>webpack 使用 enhanced-resolve 来解析文件路径</p><ul><li>绝对路径 <ul><li>不需要进步解析</li></ul></li><li>相对路径 <ul><li>使用 import 或者 require 的资源文件所出的目录 ,被认为是上下文目录</li><li>在 import / require 中给定的相对路径, 会拼接此上下文路径,来生成模块的绝对路径</li></ul></li><li>模块路径 <ul><li>在 resolve .modlues 中 指定的所有目录 检索模块 默认值是 [&#39;node_modues&#39;] 所以默认会从 node_modules 中查找文件</li><li>可以通过 alias 设置别名的方式替换</li></ul></li></ul><p>Webpack 在启动后会从配置的入口模块出发找出所有依赖的模块，Resolve 配置 Webpack 如何寻找模块所对应的文件。</p><h2 id="路径别名-alias"><a class="header-anchor" href="#路径别名-alias" aria-hidden="true">#</a> 路径别名 alias</h2><p><code>resolve.alias</code> 配置项通过别名来把原导入路径映射成一个新的导入路径。例如使用以下配置：</p><div class="language-js"><pre><code><span class="token comment">// Webpack alias 配置</span>
resolve<span class="token operator">:</span> <span class="token punctuation">{</span>
  alias<span class="token operator">:</span> <span class="token punctuation">{</span>
    components<span class="token operator">:</span> <span class="token string">&quot;./src/components/&quot;</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>以上 alias 配置的含义是把导入语句里的 <code>components</code> 关键字替换成 <code>./src/components/</code>。</p><div class="language-js"><pre><code>resolve<span class="token operator">:</span><span class="token punctuation">{</span>
  alias<span class="token operator">:</span><span class="token punctuation">{</span>
    <span class="token string">&#39;vue$&#39;</span><span class="token operator">:</span> <span class="token string">&#39;/path/to/react.min.js&#39;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p><code>vue$</code> 只会命中以 <code>vue</code> 结尾的导入语句，即只会把 <code>import &#39;vue</code> 关键字替换成 <code>import &#39;/path/to/react.min.js&#39;</code>。</p><ul><li><p>如果是一个文件</p><ul><li>如果文件具有扩展名, 则直接打包文件</li><li>否则, 将使用 resolve.exentsion 是选项作文文件扩展名解析</li></ul></li><li><p>如果是一个文件夹</p><ul><li>会在文件夹中根据 resolve.mainFiles 配置选项中指定的文件顺序查找 <ul><li>resolve.mainFiles 的默认值是 [&#39;index&#39;]</li><li>再根据 resolve,extensions 来解析扩展名</li></ul></li></ul></li></ul><h2 id="省略后缀-extensions"><a class="header-anchor" href="#省略后缀-extensions" aria-hidden="true">#</a> 省略后缀 extensions</h2><p>在导入语句没带文件后缀时，Webpack 会自动带上后缀后去尝试访问文件是否存在。 <code>resolve.extensions</code> 用于配置在尝试过程中用到的后缀列表，默认是：</p><div class="language-js"><pre><code>extensions<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;.js&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;.json&quot;</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</code></pre></div><p>也就是说当遇到 <code>require(&#39;./data&#39;)</code> 这样的导入语句时，Webpack 会先去寻找 <code>./data.js</code> 文件，如果该文件不存在就去寻找 <code>./data.json</code> 文件， 如果还是找不到就报错。</p><p>假如你想让 Webpack 优先使用目录下的 TypeScript 文件，可以这样配置：</p><div class="language-javascript"><pre><code>extensions<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;.ts&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;.js&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;.json&quot;</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="缩写路径-modules"><a class="header-anchor" href="#缩写路径-modules" aria-hidden="true">#</a> 缩写路径 modules</h2><p><code>resolve.modules</code> 配置 Webpack 去哪些目录下寻找第三方模块，默认是只会去 <code>node_modules</code> 目录下寻找。 有时你的项目里会有一些模块会大量被其它模块依赖和导入，由于其它模块的位置分布不定，针对不同的文件都要去计算被导入模块文件的相对路径， 这个路径有时候会很长，就像这样 <code>import &#39;../../../components/button&#39;</code> 这时你可以利用 <code>modules</code> 配置项优化，假如那些被大量导入的模块都在 <code>./src/components</code> 目录下，把 <code>modules</code> 配置成</p><div class="language-js"><pre><code>modules<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;./src/components&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;node_modules&quot;</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</code></pre></div><p>后，你可以简单通过 <code>import &#39;button&#39;</code> 导入。</p><h2 id="externals"><a class="header-anchor" href="#externals" aria-hidden="true">#</a> externals</h2><p>排除打包项</p><div class="language-"><pre><code>externals: {
	&#39;jquery&#39;: &#39;jquery&#39;
},
</code></pre></div><h2 id="enforceextension"><a class="header-anchor" href="#enforceextension" aria-hidden="true">#</a> enforceExtension</h2><div class="language-"><pre><code>resolve.enforceExtension` 如果配置为 `true` 所有导入语句都必须要带文件后缀， 例如开启前 `import &#39;./foo&#39;` 能正常工作，开启后就必须写成 `import &#39;./foo.js&#39;
</code></pre></div><h1 id="devserver"><a class="header-anchor" href="#devserver" aria-hidden="true">#</a> devServer</h1><p>devserver 也是有对我们的源代码进行打包的,但是没有进行文件的输出,而是打包进了内存中,通过 express 服务器访问内存中的资源</p><p>​ 内部使用了 memfs 这个内存的文件系统</p><h2 id="host"><a class="header-anchor" href="#host" aria-hidden="true">#</a> host</h2><p>配置项用于配置 DevServer 服务监听的地址。 例如你想要局域网中的其它设备访问你本地的服务，可以在启动 DevServer 时带上 <code>--host 0.0.0.0</code>。 <code>host</code> 的默认值是 <code>127.0.0.1</code> 即只有本地可以访问 DevServer 的 HTTP 服务。</p><ul><li><p>loaclhost 本质上是一个域名 ,通常情况下 会被解析成 127.0.0.1</p></li><li><p>127.0.0.1: 回环地址, 表达的意思是我们主机自己发出去的包, 直接被直接接收</p><ul><li>正常的数据包库经常是 应用层--传输层--网络层--数据链路层--物理层</li><li>而回环地址, 是在网络层直接就被获取到了, 是不会经过数据链路层和物理层的</li><li>比如我们监听的 127.0.0.0 时,在同一个网段的主机中.通过 ip 地址是不能访问的</li></ul></li><li><p>0.0.0.0 监听 ipv4 上所有的地址,在根据端口找到不同的应用程序</p><ul><li>比如我们舰体 0.0.0 时,在同一个网段下的主机中,通过 ip 地址是可以访问的</li></ul></li></ul><h2 id="port"><a class="header-anchor" href="#port" aria-hidden="true">#</a> port</h2><p><code>devServer.port</code> 配置项用于配置 DevServer 服务监听的端口，默认使用 8080 端口。 如果 8080 端口已经被其它程序占有就使用 8081，如果 8081 还是被占用就使用 8082，以此类推。</p><h2 id="模块热替换-hmr"><a class="header-anchor" href="#模块热替换-hmr" aria-hidden="true">#</a> 模块热替换 HMR</h2><h3 id="hot-livereload"><a class="header-anchor" href="#hot-livereload" aria-hidden="true">#</a> hot/ liveReload</h3><p>webpack 5 中 启动自动更新 热更新只适用于 web 相关的 targets 在 devserver 外部 配置 target: &#39;web&#39;</p><p>DevServer 默认的行为是在发现源代码被更新后会通过自动刷新整个页面来做到实时预览，开启模块热替换功能后将在不刷新整个页面的情况下通过用新模块替换老模块来做到实时预览。</p><h4 id="指定模块热替换"><a class="header-anchor" href="#指定模块热替换" aria-hidden="true">#</a> 指定模块热替换</h4><div class="language-javascript"><pre><code><span class="token comment">//  指定一个模块进行热替换</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>module<span class="token punctuation">.</span>hot<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  module<span class="token punctuation">.</span>hot<span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span><span class="token string">&quot;../xx/xxx.xxx.js&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 接受一个回调函数,但 模块发生改变的时候 执行这个回调函数</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h4 id="其他模块进行热替换"><a class="header-anchor" href="#其他模块进行热替换" aria-hidden="true">#</a> 其他模块进行热替换</h4><p>在我们一般使用 vue 进行开发 不需要一个个模块单独的进行设置</p><p>vue--loader 已经内置了 vue 项目中各个组件的 热替换</p><h4 id="hmr-的原理"><a class="header-anchor" href="#hmr-的原理" aria-hidden="true">#</a> HMR 的原理</h4><p>HMR 是如何做到只更新一个模块中的内容?</p><ul><li><p>webpack-dev-server 会创建两个服务:</p><ol><li>提供静态资源的服务(express)</li><li>Socket(net.Socket)s</li></ol></li><li><p>express 负责直接提供静态资源的服务(打包后的资源直接被浏览器请求和解析)</p></li><li><p>HMR Socket Server, 是一个 socket 的长连接 通过 心跳包 判断客户端存不存在 保持一条通道</p><ul><li>长连接一个最大的好处就是 建立连接之后双方可以通信 (服务器可以直接发送文件到客户端)</li><li>当服务器监听到对应模块发生改变时,会产生两个 json 文件(manifes 文件), 和 js 文件 (update chunk)</li><li>通过长连接, 可以直接将两个文件主动发送给客户端 (浏览器)</li><li>浏览器拿到这两个新文件后, 通过 HMR runtime 机制. 加载这两个文件. 并且针对修改的模块进行更新</li></ul></li></ul><h2 id="proxy"><a class="header-anchor" href="#proxy" aria-hidden="true">#</a> Proxy</h2><p>配置代理: 解决接口跨域问题</p><ol><li></li></ol><div class="language-javascript"><pre><code>proxy<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token string">&#39;api&#39;</span> <span class="token operator">:</span> <span class="token punctuation">{</span>
        target<span class="token operator">:</span> <span class="token string">&#39;https: //api.xxxx.com&#39;</span><span class="token punctuation">,</span>
        pathRewrite<span class="token operator">:</span> <span class="token punctuation">{</span>
			<span class="token string">&#39;^api&#39;</span><span class="token operator">:</span> <span class="token string">&#39;&#39;</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span>
      <span class="token comment">// 不能使用loaclhost 直接访问 xxx.com    需要开启</span>
      changeOrigin<span class="token operator">:</span> <span class="token boolean">true</span>
      secour<span class="token operator">:</span> <span class="token boolean">false</span>
            <span class="token comment">//  支持https 等安全协议</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="historyapifallback"><a class="header-anchor" href="#historyapifallback" aria-hidden="true">#</a> HistoryApiFallback</h2><p><code>devServer.historyApiFallback</code> 用于方便的开发使用了 <a href="https://developer.mozilla.org/en-US/docs/Web/API/History" target="_blank" rel="noopener noreferrer">HTML5 History API</a> 的单页应用。 这类单页应用要求服务器在针对任何命中的路由时都返回一个对应的 HTML 文件，例如在访问 <code>http://localhost/user</code> 和 <code>http://localhost/home</code> 时都返回 <code>index.html</code> 文件， 浏览器端的 JavaScript 代码会从 URL 里解析出当前页面的状态，显示出对应的界面。</p><p>配置 <code>historyApiFallback</code> 最简单的做法是：</p><div class="language-js"><pre><code>historyApiFallback<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
</code></pre></div><p>这会导致任何请求都会返回 <code>index.html</code> 文件，这只能用于只有一个 HTML 文件的应用。</p><p>如果你的应用由多个单页应用组成，这就需要 DevServer 根据不同的请求来返回不同的 HTML 文件，配置如下：</p><div class="language-js"><pre><code>historyApiFallback<span class="token operator">:</span> <span class="token punctuation">{</span>
  <span class="token comment">// 使用正则匹配命中路由</span>
  rewrites<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token comment">// /user 开头的都返回 user.html</span>
    <span class="token punctuation">{</span> from<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\/user</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> to<span class="token operator">:</span> <span class="token string">&quot;/user.html&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span> from<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^\/game</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> to<span class="token operator">:</span> <span class="token string">&quot;/game.html&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token comment">// 其它的都返回 index.html</span>
    <span class="token punctuation">{</span> from<span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">.</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> to<span class="token operator">:</span> <span class="token string">&quot;/index.html&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="contentbase"><a class="header-anchor" href="#contentbase" aria-hidden="true">#</a> contentBase</h2><p><code>devServer.contentBase</code> 配置 DevServer HTTP 服务器的文件根目录。 默认情况下为当前执行目录，通常是项目根目录，\</p><p>但我们想使用从 webpack 打包之后的资源, 可以在这个目录下</p><p>使用场景 ,一些图片, 图标等资源等到生成阶段才进行复制</p><div class="language-js"><pre><code>devServer<span class="token operator">:</span> <span class="token punctuation">{</span>
  contentBase<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;public&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>这里需要指出可能会让你疑惑的地方，DevServer 服务器通过 HTTP 服务暴露出的文件分为两类：</p><ul><li>暴露本地文件。</li><li>暴露 Webpack 构建出的结果，由于构建出的结果交给了 DevServer，所以你在使用了 DevServer 时在本地找不到构建出的文件。</li></ul><p><code>contentBase</code> 只能用来配置暴露本地文件的规则，你可以通过 <code>contentBase:false</code> 来关闭暴露本地文件。</p><h2 id="注入响应头-headers"><a class="header-anchor" href="#注入响应头-headers" aria-hidden="true">#</a> 注入响应头 headers</h2><p><code>devServer.headers</code> 配置项可以在 HTTP 响应中注入一些 HTTP 响应头，使用如下：</p><div class="language-js"><pre><code>devServer<span class="token operator">:</span><span class="token punctuation">{</span>
  headers<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token string">&#39;X-foo&#39;</span><span class="token operator">:</span><span class="token string">&#39;bar&#39;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="开启白名单-allowedhosts"><a class="header-anchor" href="#开启白名单-allowedhosts" aria-hidden="true">#</a> 开启白名单 allowedHosts</h2><p><code>devServer.allowedHosts</code> 配置一个白名单列表，只有 HTTP 请求的 HOST 在列表里才正常返回，使用如下：</p><div class="language-js"><pre><code>allowedHosts<span class="token operator">:</span> <span class="token punctuation">[</span>
  <span class="token comment">// 匹配单个域名</span>
  <span class="token string">&quot;host.com&quot;</span><span class="token punctuation">,</span>
  <span class="token string">&quot;sub.host.com&quot;</span><span class="token punctuation">,</span>
  <span class="token comment">// host2.com 和所有的子域名 *.host2.com 都将匹配</span>
  <span class="token string">&quot;.host2.com&quot;</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="host-检查-disablehostcheck"><a class="header-anchor" href="#host-检查-disablehostcheck" aria-hidden="true">#</a> HOST 检查 disableHostCheck</h2><p><code>devServer.disableHostCheck</code> 配置项用于配置是否关闭用于 DNS 重绑定的 HTTP 请求的 HOST 检查。 DevServer 默认只接受来自本地的请求，关闭后可以接受来自任何 HOST 的请求。 它通常用于搭配 <code>--host 0.0.0.0</code> 使用，因为你想要其它设备访问你本地的服务，但访问时是直接通过 IP 地址访问而不是 HOST 访问，所以需要关闭 HOST 检查。</p><h2 id="https"><a class="header-anchor" href="#https" aria-hidden="true">#</a> https</h2><p>DevServer 默认使用 HTTP 协议服务，它也能通过 HTTPS 协议服务。 有些情况下你必须使用 HTTPS，例如 HTTP2 和 Service Worker 就必须运行在 HTTPS 之上。 要切换成 HTTPS 服务，最简单的方式是：</p><div class="language-js"><pre><code>devServer<span class="token operator">:</span> <span class="token punctuation">{</span>
  https<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>DevServer 会自动的为你生成一份 HTTPS 证书。</p><p>如果你想用自己的证书可以这样配置：</p><div class="language-js"><pre><code>devServer<span class="token operator">:</span><span class="token punctuation">{</span>
  https<span class="token operator">:</span> <span class="token punctuation">{</span>
    key<span class="token operator">:</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span><span class="token string">&#39;path/to/server.key&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    cert<span class="token operator">:</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span><span class="token string">&#39;path/to/server.crt&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    ca<span class="token operator">:</span> fs<span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span><span class="token string">&#39;path/to/ca.pem&#39;</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="开启压缩-compress"><a class="header-anchor" href="#开启压缩-compress" aria-hidden="true">#</a> 开启压缩 compress</h2><p><code>devServer.compress</code> 配置是否启用 gzip 压缩。<code>boolean</code> 为类型，默认为 <code>false</code>。</p><p>不对 html 进行压缩 一般不开启 因为本来就是在本地进行开发测试, 增加了压缩 解压成本</p><img src="/interview/assets/开启的compress压缩.e97cf8c3.png" style="zoom:100%;"> ## open <p><code>devServer.open</code> 用于在 DevServer 启动且第一次构建完时自动用你系统上默认的浏览器去打开要开发的网页。 同时还提供 <code>devServer.openPage</code> 配置项用于打开指定 URL 的网页。&#39;</p><h1 id="module-federation-模块联邦"><a class="header-anchor" href="#module-federation-模块联邦" aria-hidden="true">#</a> Module Federation (模块联邦 )</h1><p>模块联邦 多个应用, 可以共享一个模块 (本地可以调用远程的模块)</p><ul><li><p>提供方模块</p><ul><li>name : 当前应用名称 (提供调用方使用)</li><li>filename: 打包后的文件名称 (提供调用方使用)</li><li>expses: 暴露模块 (相当与 export 导出) <ul><li>模块名称: 模块文件路径</li></ul></li></ul></li><li><p>模块使用方</p><ul><li>remote : 导入模块 (相当于 import) <ul><li>导入后的别名: &quot;远程应用名称@远程地址/远程导出的文件名&quot;</li></ul></li></ul></li></ul><h2 id="使用"><a class="header-anchor" href="#使用" aria-hidden="true">#</a> 使用</h2><p>创建两个应用 创建两个应用 app1 和 app2</p><div class="language-"><pre><code>mkdir app1
cd app1
npm init -y

npm install webpack webpack-cli html-webpack-plugin webpack-dev-server -D
</code></pre></div><p>然后创建 src 目录，并创建入口文件 ./src/index.js 和模板文件 ./src/index.html</p><p>app2 按照相同的方式创建</p><h2 id="app1-声明共用模块"><a class="header-anchor" href="#app1-声明共用模块" aria-hidden="true">#</a> App1 声明共用模块</h2><p>声明模块</p><div class="language-javascript"><pre><code><span class="token comment">// Sitename.js</span>
<span class="token comment">// 站点名称</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&#39;来自 app1 的共用模块&#39;</span><span class="token punctuation">)</span>

  <span class="token keyword">const</span> element <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">&#39;h2&#39;</span><span class="token punctuation">)</span>
  element<span class="token punctuation">.</span>textContent <span class="token operator">=</span> name

  <span class="token keyword">return</span> element
<span class="token punctuation">}</span>
在入口文件中引入

<span class="token keyword">import</span> sitename <span class="token keyword">from</span> <span class="token string">&#39;./Sitename.js&#39;</span>

<span class="token keyword">const</span> title <span class="token operator">=</span> <span class="token function">sitename</span><span class="token punctuation">(</span><span class="token string">&#39;应用 A&#39;</span><span class="token punctuation">)</span>
document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>title<span class="token punctuation">)</span>
在 webpack<span class="token punctuation">.</span>config<span class="token punctuation">.</span>js 中，使用联邦模块插件

<span class="token keyword">const</span> Mfp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">&#39;webpack&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span>ModuleFederationPlugin<span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token punctuation">{</span> resolve <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">&#39;path&#39;</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> HtmlWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">&#39;html-webpack-plugin&#39;</span><span class="token punctuation">)</span>
<span class="token comment">// 导入模块联邦插件</span>
<span class="token keyword">const</span> Mfp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">&#39;webpack&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span>ModuleFederationPlugin<span class="token punctuation">;</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token comment">// mode 工作模式</span>
  mode<span class="token operator">:</span> <span class="token string">&#39;development&#39;</span><span class="token punctuation">,</span>

  <span class="token comment">// 入口</span>
  entry<span class="token operator">:</span> <span class="token string">&#39;./src/index.js&#39;</span><span class="token punctuation">,</span>

  <span class="token comment">// 出口</span>
  output<span class="token operator">:</span> <span class="token punctuation">{</span>
    path<span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&#39;dist&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    filename<span class="token operator">:</span> <span class="token string">&#39;bundle.js&#39;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token comment">// 模块</span>
  module<span class="token operator">:</span> <span class="token punctuation">{</span>
    rules<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">]</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token comment">// 插件</span>
  plugins<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      template<span class="token operator">:</span> <span class="token string">&#39;./src/index.html&#39;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">Mfp</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      <span class="token comment">// 对外提供的打包后的文件名（引入时使用）</span>
      filename<span class="token operator">:</span> <span class="token string">&#39;app1.js&#39;</span><span class="token punctuation">,</span>
      <span class="token comment">// 当前应用模块名称</span>
      name<span class="token operator">:</span> <span class="token string">&#39;app1&#39;</span><span class="token punctuation">,</span>
      <span class="token comment">// 暴露模块</span>
      exposes<span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token comment">// 名称： 代码路径</span>
        <span class="token string">&#39;./Sitename&#39;</span><span class="token operator">:</span> <span class="token string">&#39;./src/Sitename.js&#39;</span><span class="token punctuation">,</span>
        <span class="token comment">// &#39;./Carousel&#39;: &#39;./src/Carousel.js&#39;,</span>
        <span class="token comment">// &#39;./Pagination&#39;: &#39;./src/Pagination.js&#39;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>

  <span class="token comment">// 服务器</span>
  devServer<span class="token operator">:</span> <span class="token punctuation">{</span>
    contentBase<span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&#39;dist&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    port<span class="token operator">:</span> <span class="token number">3001</span><span class="token punctuation">,</span>
    open<span class="token operator">:</span> <span class="token boolean">true</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="app2-引入共用模块"><a class="header-anchor" href="#app2-引入共用模块" aria-hidden="true">#</a> App2 引入共用模块</h2><div class="language-javascript"><pre><code><span class="token keyword">const</span> <span class="token punctuation">{</span> resolve <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">&quot;path&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> HtmlWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">&quot;html-webpack-plugin&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 模块联邦</span>
<span class="token keyword">const</span> Mfp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">&quot;webpack&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span>ModuleFederationPlugin<span class="token punctuation">;</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token comment">// mode 工作模式</span>
  mode<span class="token operator">:</span> <span class="token string">&quot;development&quot;</span><span class="token punctuation">,</span>

  <span class="token comment">// 入口</span>
  entry<span class="token operator">:</span> <span class="token string">&quot;./src/index.js&quot;</span><span class="token punctuation">,</span>

  <span class="token comment">// 出口</span>
  output<span class="token operator">:</span> <span class="token punctuation">{</span>
    path<span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;dist&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    filename<span class="token operator">:</span> <span class="token string">&quot;bundle.js&quot;</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token comment">// 模块</span>
  module<span class="token operator">:</span> <span class="token punctuation">{</span>
    rules<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token comment">// 插件</span>
  plugins<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      template<span class="token operator">:</span> <span class="token string">&quot;./src/index.html&quot;</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">Mfp</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      <span class="token comment">// 导入模块</span>
      remotes<span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token comment">// 导入后给模块起个别名：“微应用名称@地址/导出的文件名”</span>
        appone<span class="token operator">:</span> <span class="token string">&quot;app1@http://localhost:3001/app1.js&quot;</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token comment">// 应用 B 也可以对外提供模块，因此，也可以配置 filename 和 name</span>
      filename<span class="token operator">:</span> <span class="token string">&quot;app2.js&quot;</span><span class="token punctuation">,</span>
      <span class="token comment">// 应用名称，当前模块自己的名字</span>
      name<span class="token operator">:</span> <span class="token string">&quot;app2&quot;</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>

  <span class="token comment">// 服务器</span>
  devServer<span class="token operator">:</span> <span class="token punctuation">{</span>
    contentBase<span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">&quot;dist&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    port<span class="token operator">:</span> <span class="token number">3002</span><span class="token punctuation">,</span>
    open<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="在-app2-中使用-app1-的模块"><a class="header-anchor" href="#在-app2-中使用-app1-的模块" aria-hidden="true">#</a> 在 App2 中使用 App1 的模块</h2><div class="language-javascript"><pre><code><span class="token comment">// app1/src/index.js</span>

<span class="token comment">// 调用 app1 中的模块</span>
<span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">&quot;appone/Sitename&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// res.default()</span>
  <span class="token keyword">const</span> title <span class="token operator">=</span> res<span class="token punctuation">.</span><span class="token function">default</span><span class="token punctuation">(</span><span class="token string">&quot;应用 B&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>title<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">&quot;appone/Carousel&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">default</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">&quot;appone/Pagination&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">default</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h1 id="判断如何配置-webpack"><a class="header-anchor" href="#判断如何配置-webpack" aria-hidden="true">#</a> 判断如何配置 webpack</h1><ul><li>想让源文件加入到构建流程中去被 Webpack 控制，配置 <code>entry</code>。</li><li>想自定义输出文件的位置和名称，配置 <code>output</code>。</li><li>想自定义寻找依赖模块时的策略，配置 <code>resolve</code>。</li><li>想自定义解析和转换文件的策略，配置 <code>module</code>，通常是配置 <code>module.rules</code> 里的 Loader。</li><li>其它的大部分需求可能要通过 Plugin 去实现，配置 <code>plugin</code>。</li></ul></div></div><footer class="page-footer" data-v-7eddb2c4 data-v-fb8d84c6><div class="edit" data-v-fb8d84c6><div class="edit-link" data-v-fb8d84c6 data-v-1ed99556><!----></div></div><div class="updated" data-v-fb8d84c6><!----></div></footer><div class="next-and-prev-link" data-v-7eddb2c4 data-v-38ede35f><div class="container" data-v-38ede35f><div class="prev" data-v-38ede35f><a class="link" href="/interview/Vue/source/nextTick" data-v-38ede35f><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon icon-prev" data-v-38ede35f><path d="M19,11H7.4l5.3-5.3c0.4-0.4,0.4-1,0-1.4s-1-0.4-1.4,0l-7,7c-0.1,0.1-0.2,0.2-0.2,0.3c-0.1,0.2-0.1,0.5,0,0.8c0.1,0.1,0.1,0.2,0.2,0.3l7,7c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4L7.4,13H19c0.6,0,1-0.4,1-1S19.6,11,19,11z"></path></svg><span class="text" data-v-38ede35f>nextTick</span></a></div><div class="next" data-v-38ede35f><a class="link" href="/interview/WebPack/optimize" data-v-38ede35f><span class="text" data-v-38ede35f>优化方案</span><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon icon-next" data-v-38ede35f><path d="M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"></path></svg></a></div></div></div><!--[--><!--]--></div></main></div><!----><!--]--></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"index.md\":\"992e2bc4\",\"css_advanced.md\":\"157298f3\",\"css_index.md\":\"0df1ef28\",\"browser_advanced.md\":\"a7a79457\",\"browser_index.md\":\"9938c247\",\"browser_plugin.md\":\"fd27046d\",\"git_index.md\":\"fb33a92a\",\"html_advanced.md\":\"599ad3d5\",\"html_index.md\":\"c94736b6\",\"interview_index.md\":\"07dc8acc\",\"interview_two.md\":\"0ca812f6\",\"javascript_advanced.md\":\"5c434e6d\",\"javascript_index.md\":\"d996a3fc\",\"jenkins_index.md\":\"3068e232\",\"myself_index.md\":\"340fc837\",\"myself_one.md\":\"31202d59\",\"myself_pre.md\":\"aa93248e\",\"network_index.md\":\"7251e8b9\",\"network_security.md\":\"d11dae3c\",\"node_index.md\":\"e0b22fc7\",\"node_pit.md\":\"a1502c64\",\"npm_index.md\":\"59b033b6\",\"pit_index.md\":\"603d46aa\",\"solution_index.md\":\"987aa705\",\"typescript_advanced.md\":\"431b8bba\",\"typescript_combat.md\":\"60c9a8a2\",\"typescript_index.md\":\"bd88b5a2\",\"vite_index.md\":\"d6838c03\",\"vite_optimize.md\":\"49f1bb24\",\"vue_index.md\":\"380ec221\",\"vue_reactive.md\":\"206c8e46\",\"vue_router.md\":\"0d556c25\",\"vue_source.md\":\"592e192a\",\"vue_vuex.md\":\"032502ef\",\"webpack_advanced.md\":\"ae6c63b7\",\"webpack_common.md\":\"141deb7a\",\"webpack_custom.md\":\"4827ebf8\",\"webpack_index.md\":\"49f185a6\",\"webpack_optimize.md\":\"545698f9\",\"vue_source_index.md\":\"1c12bc29\",\"vue_source_nexttick.md\":\"4533a28b\",\"vue_source_watch.md\":\"0e7342fc\"}")</script>
    <script type="module" async src="/interview/assets/app.49accf37.js"></script>
  </body>
</html>